package com.gzk.hrm.service.impl;

import com.gzk.hrm.doc.CourseDoc;
import com.gzk.hrm.mapper.HighlightResultMapper;
import com.gzk.hrm.page.AggPageList;
import com.gzk.hrm.query.CourseQuery;
import com.gzk.hrm.repository.CourseElasticSearchRepository;
import com.gzk.hrm.result.AggResult;
import com.gzk.hrm.service.ICourseElasticSearchService;
import com.gzk.hrm.util.PageList;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;

@Service
public class CourseElasticSearchServiceImpl implements ICourseElasticSearchService {

    @Autowired
    private CourseElasticSearchRepository repository;

    @Override
    public void saveCourse(CourseDoc doc) {
        repository.save(doc);
    }

    @Override
    public void deleteCourse(Long id) {
        repository.deleteById(id);
    }

    @Autowired
    private ElasticsearchTemplate template;

    @Autowired
    private HighlightResultMapper highlightResultMapper;

    @Override
    public PageList<CourseDoc> searchCourse(CourseQuery query) {
        //创建本地搜索查询条件构建器
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();

        //设置index
        builder.withIndices("hrmtest");
        //设置type
        builder.withTypes("course");

        //设置查询条件

        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //设置must里面的查询参数
        if (StringUtils.hasLength(query.getKeyword())){
            boolQueryBuilder.must(QueryBuilders.wildcardQuery("name", query.getKeyword()));
        }
        //设置filter里面的查询参数
        if (query.getCourseTypeId() != null){
            boolQueryBuilder.filter(QueryBuilders.termQuery("courseTypeId", query.getCourseTypeId()));
        }
        if(StringUtils.hasLength(query.getGradeName())){
            boolQueryBuilder.filter(QueryBuilders.termQuery("gradeName", query.getGradeName()));
        }
        if(StringUtils.hasLength(query.getTenantName())){
            boolQueryBuilder.filter(QueryBuilders.termQuery("tenantName", query.getTenantName()));
        }
        if(query.getPriceMax() != null){
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").lte(query.getPriceMax()));
        }
        if(query.getPriceMin() != null){
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(query.getPriceMin()));
        }

        //设置条件
        builder.withQuery(boolQueryBuilder);


        //设置分页
        builder.withPageable(PageRequest.of(query.getPage()-1,query.getRows()));

        //确定排序字段
        String sortField = "price";
        //默认排序规则
        SortOrder sortOrder = SortOrder.ASC;
        //设置排序
        if(StringUtils.hasLength(query.getSortField())){

            switch (query.getSortField().toLowerCase()){
                case "xl": sortField = "saleCount";break;
                case "xp": sortField = "onlineTime";break;
                case "pl": sortField = "commentCount";break;
                case "jg": sortField = "price";break;
                case "rq": sortField = "viewCount";break;
                default: sortField = "price";break;
            }

            //判断排序规则是否有值
            if(StringUtils.hasLength(query.getSortType())){
                if(query.getSortType().equalsIgnoreCase("desc")){
                    sortOrder = SortOrder.DESC;
                }
            }
        }

        builder.withSort(new FieldSortBuilder(sortField).order(sortOrder));

        //高亮
        HighlightBuilder.Field field = new HighlightBuilder.Field("name");
        field.preTags("<font style='color:red'>");
        field.postTags("</font>");
        builder.withHighlightFields(field);


        //聚合
        TermsAggregationBuilder tenantTermAgg = AggregationBuilders.terms("tenantTermAgg");
        tenantTermAgg.field("tenantName");
        builder.addAggregation(tenantTermAgg);

        TermsAggregationBuilder gradeTermAgg = AggregationBuilders.terms("gradeNameTermAgg");
        gradeTermAgg.field("gradeName");
        builder.addAggregation(gradeTermAgg);

        //构建搜索查询
        SearchQuery searchQuery = builder.build();

        //执行
        //Page<CourseDoc> page = repository.search(searchQuery);
        AggregatedPage<CourseDoc> page = template.queryForPage(searchQuery, CourseDoc.class, highlightResultMapper);

        //封装结果集
        Aggregations aggregations = page.getAggregations();
        Map<String, Aggregation> resultMap = aggregations.getAsMap();
        //用KeySet的方式来遍历数据
        Set<String> resultMapKeys = resultMap.keySet();
        //创建聚合结果集对象
        HashMap<String, List<AggResult>> aggMap = new HashMap<>();
        //遍历
        for (String resultMapKey : resultMapKeys) {

            //创建list
            List<AggResult> aggList = new ArrayList<>();
            Aggregation aggregation = resultMap.get(resultMapKey);
            StringTerms resultStringTerms = (StringTerms) aggregation;
            List<StringTerms.Bucket> buckets = resultStringTerms.getBuckets();
            buckets.forEach(bucket -> {
                //ES中聚合的字段名
                String key = (String) bucket.getKey();
                long docCount = bucket.getDocCount();
                //添加集合
                aggList.add(new AggResult(key,docCount));
            });

            //添加map
            aggMap.put(resultMapKey, aggList);
        }

        return new AggPageList<>(page.getTotalElements(),page.getContent(),aggMap);
    }
}
